cmp x0, x20
b.ne _panic
+ /* ---------------------------------------------
+ * Invalidate the RW memory used by the BL2
+ * image. This includes the data and NOBITS
+ * sections. This is done to safeguard against
+ * possible corruption of this memory by dirty
+ * cache lines in a system cache as a result of
+ * use by an earlier boot loader stage.
+ * ---------------------------------------------
+ */
+ adr x0, __RW_START__
+ adr x1, __RW_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+
/* ---------------------------------------------
* Zero out NOBITS sections. There are 2 of them:
* - the .bss section;
__RO_END__ = .;
} >RAM
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
.data . : {
__DATA_START__ = .;
*(.data*)
} >RAM
#endif
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
__BL2_END__ = .;
__BSS_SIZE__ = SIZEOF(.bss);
*/
bl bl31_main
+ /* -------------------------------------------------------------
+ * Clean the .data & .bss sections to main memory. This ensures
+ * that any global data which was initialised by the primary CPU
+ * is visible to secondary CPUs before they enable their data
+ * caches and participate in coherency.
+ * -------------------------------------------------------------
+ */
+ adr x0, __DATA_START__
+ adr x1, __DATA_END__
+ sub x1, x1, x0
+ bl clean_dcache_range
+
+ adr x0, __BSS_START__
+ adr x1, __BSS_END__
+ sub x1, x1, x0
+ bl clean_dcache_range
+
b el3_exit
endfunc bl31_entrypoint
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
"cpu_ops not defined for this platform.")
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
.data . : {
__DATA_START__ = .;
*(.data*)
} >RAM
#endif
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
__BL31_END__ = .;
__BSS_SIZE__ = SIZEOF(.bss);
INFO("BL3-1: Initializing runtime services\n");
runtime_svc_init();
- /* Clean caches before re-entering normal world */
- dcsw_op_all(DCCSW);
-
/*
* All the cold boot actions on the primary cpu are done. We now need to
* decide which is the next image (BL32 or BL33) and how to execute it.
msr sctlr_el1, x0
isb
+ /* ---------------------------------------------
+ * Invalidate the RW memory used by the BL32
+ * image. This includes the data and NOBITS
+ * sections. This is done to safeguard against
+ * possible corruption of this memory by dirty
+ * cache lines in a system cache as a result of
+ * use by an earlier boot loader stage.
+ * ---------------------------------------------
+ */
+ adr x0, __RW_START__
+ adr x1, __RW_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+
/* ---------------------------------------------
* Zero out NOBITS sections. There are 2 of them:
* - the .bss section;
__RO_END__ = .;
} >RAM
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
.data . : {
__DATA_START__ = .;
*(.data*)
} >RAM
#endif
+ /*
+ * Define a linker symbol to mark the end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
__BL32_END__ = .;
__BSS_SIZE__ = SIZEOF(.bss);
* ---------------------------------------------------------------------
*/
.if \_init_c_runtime
+#if IMAGE_BL31
+ /* -------------------------------------------------------------
+ * Invalidate the RW memory used by the BL31 image. This
+ * includes the data and NOBITS sections. This is done to
+ * safeguard against possible corruption of this memory by
+ * dirty cache lines in a system cache as a result of use by
+ * an earlier boot loader stage.
+ * -------------------------------------------------------------
+ */
+ adr x0, __RW_START__
+ adr x1, __RW_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+#endif /* IMAGE_BL31 */
+
ldr x0, =__BSS_START__
ldr x1, =__BSS_SIZE__
bl zeromem16
DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w)
void flush_dcache_range(uint64_t, uint64_t);
+void clean_dcache_range(uint64_t, uint64_t);
void inv_dcache_range(uint64_t, uint64_t);
void dcsw_op_louis(uint32_t);
void dcsw_op_all(uint32_t);
#include <asm_macros.S>
.globl flush_dcache_range
+ .globl clean_dcache_range
.globl inv_dcache_range
.globl dcsw_op_louis
.globl dcsw_op_all
.globl dcsw_op_level2
.globl dcsw_op_level3
- /* ------------------------------------------
- * Clean+Invalidate from base address till
- * size. 'x0' = addr, 'x1' = size
- * ------------------------------------------
- */
-func flush_dcache_range
+/*
+ * This macro can be used for implementing various data cache operations `op`
+ */
+.macro do_dcache_maintenance_by_mva op
dcache_line_size x2, x3
add x1, x0, x1
sub x3, x2, #1
bic x0, x0, x3
-flush_loop:
- dc civac, x0
+loop_\op:
+ dc \op, x0
add x0, x0, x2
cmp x0, x1
- b.lo flush_loop
+ b.lo loop_\op
dsb sy
ret
+.endm
+ /* ------------------------------------------
+ * Clean+Invalidate from base address till
+ * size. 'x0' = addr, 'x1' = size
+ * ------------------------------------------
+ */
+func flush_dcache_range
+ do_dcache_maintenance_by_mva civac
endfunc flush_dcache_range
+ /* ------------------------------------------
+ * Clean from base address till size.
+ * 'x0' = addr, 'x1' = size
+ * ------------------------------------------
+ */
+func clean_dcache_range
+ do_dcache_maintenance_by_mva cvac
+endfunc clean_dcache_range
/* ------------------------------------------
* Invalidate from base address till
* ------------------------------------------
*/
func inv_dcache_range
- dcache_line_size x2, x3
- add x1, x0, x1
- sub x3, x2, #1
- bic x0, x0, x3
-inv_loop:
- dc ivac, x0
- add x0, x0, x2
- cmp x0, x1
- b.lo inv_loop
- dsb sy
- ret
+ do_dcache_maintenance_by_mva ivac
endfunc inv_dcache_range
/* ---------------------------------------------------------------------------
* Disable the MMU at EL3
- * This is implemented in assembler to ensure that the data cache is cleaned
- * and invalidated after the MMU is disabled without any intervening cacheable
- * data accesses
* ---------------------------------------------------------------------------
*/
bic x0, x0, x1
msr sctlr_el3, x0
isb // ensure MMU is off
- mov x0, #DCCISW // DCache clean and invalidate
- b dcsw_op_all
+ dsb sy
+ ret
endfunc disable_mmu_el3
* call to set this cpu on its way.
*/
cm_prepare_el3_exit(NON_SECURE);
-
- /* Clean caches before re-entering normal world */
- dcsw_op_louis(DCCSW);
}
psci_cpu_pd_nodes[plat_my_core_pos()].mpidr =
read_mpidr() & MPIDR_AFFINITY_MASK;
-#if !USE_COHERENT_MEM
- /*
- * The psci_non_cpu_pd_nodes only needs flushing when it's not allocated in
- * coherent memory.
- */
- flush_dcache_range((uintptr_t) &psci_non_cpu_pd_nodes,
- sizeof(psci_non_cpu_pd_nodes));
-#endif
-
- flush_dcache_range((uintptr_t) &psci_cpu_pd_nodes,
- sizeof(psci_cpu_pd_nodes));
-
psci_init_req_local_pwr_states();
/*
* call to set this cpu on its way.
*/
cm_prepare_el3_exit(NON_SECURE);
-
- /* Clean caches before re-entering normal world */
- dcsw_op_louis(DCCSW);
}